package com.shycloud.mido.member.quartz;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shycloud.mido.common.api.constants.OnlineCourseConstants;
import com.shycloud.mido.common.core.exception.BusinessException;
import com.shycloud.mido.member.api.entity.OnlineCoursePeriod;
import com.shycloud.mido.member.api.vo.OnlineCoursePeriodVO;
import com.shycloud.mido.member.mapper.BasicGoodsInfoMapper;
import com.shycloud.mido.member.mapper.OnlineCoursePeriodMapper;
import com.shycloud.mido.member.mapper.TeacherStudentMapper;
import com.shycloud.mido.organ.api.entity.TeacherStudentEntity;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.Local;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author Xiaoxing Yu
 * @date 2020/10/21 2:55 下午
 **/
@Slf4j
public class OnlineCourseEverydayJob implements Job {

	@Autowired
	private OnlineCoursePeriodMapper periodMapper;

	@Autowired
	private RedisTemplate redisTemplate;

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		String random= UUID.randomUUID().toString();
		String todayStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
		log.info("在线课每日扫描任务开始:" + random);

		try {
			List<OnlineCoursePeriodVO> timeoutList = periodMapper.selectUnfinishedPeriodListToday(
					new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

			log.info("timeout List: " + JSONObject.toJSONString(timeoutList));

			for (OnlineCoursePeriodVO periodVO: timeoutList) {
				String teacherId = periodVO.getTeacherId();
				String studentId = periodVO.getStudentId();
				if (StringUtils.isEmpty(teacherId) || StringUtils.isEmpty(studentId)) {
					log.info(StringUtils.isEmpty(teacherId) ? "teacherId is empty!" : "studentId is empty!");
					continue;
				}
				String roomId = getRoomId(studentId, teacherId);
				String teaPrefix = roomId + ":t_";
				String stuPrefix = roomId + ":s_";
				String teaLastBeatKey = teaPrefix + "_last_beat";
				String stuLastBeatKey = stuPrefix +"_last_beat";
				Long teaLastCheckPoint = (Long)redisTemplate.opsForValue().get(teaLastBeatKey);
				Long stuLastCheckPoint = (Long)redisTemplate.opsForValue().get(stuLastBeatKey);
				if (teaLastCheckPoint == null && stuLastCheckPoint == null) {
					log.info(teaLastCheckPoint == null ?
							"could not find last heartbeat for teacher with teacherId " + teacherId
							: "could not find last heartbeat for teacher with studentId " + studentId);
					continue;
				}

				Long earlierBeat = Math.min(teaLastCheckPoint, stuLastCheckPoint);

				LocalDateTime now = LocalDateTime.now();
				Long millisDiff = getDiff(toLocalDateTime(new Date(earlierBeat)), now);

				//超时20分钟的都设置Endtime为上一次heartBeat
				if ((millisDiff / (60 * 1000)) > 20) {
					periodMapper.updateMostRecentEndTimeByDate(toLocalDateTime(new Date(earlierBeat)), todayStr , periodVO.getCourseId());
				}
			}
		} catch (BusinessException e) {
		    log.error(e.getMessage(), e);
		    throw e;
		} catch (Exception e) {
		    log.error(e.getMessage(), e);
		    throw new BusinessException(e.getMessage());
		}

		log.info("在线课每日扫描任务结束:" + random);
	}

	private Long getDiff(LocalDateTime start, LocalDateTime end) {
		Duration duration = Duration.between(start, end);
		return duration.toMillis();//相差毫秒数
	}

	private String getRoomId(String studentId, String teacherId) {
		String todayStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
		return OnlineCourseConstants.REDIS_PREFIX + "_" + todayStr + ":" + teacherId.substring(0, 5) + "_" + studentId.substring(0, 5);
	}

	private LocalDateTime toLocalDateTime(Date date) {
		Instant instant = date.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();

		return instant.atZone(zoneId).toLocalDateTime();
	}

}
